package com.company

//1、接口
interface Movable {
    val maxSpeed: Int
    val wheels: Int
}

//2、抽象类
abstract class Gun(val range: Int) {
    abstract fun trigger(): String
}

class AK47(_prince: Int) : Gun(range = 100) {
    override fun trigger(): String {
        return "AK47 shooting..."
    }

}

//3、泛型 T
class MagicBox<T>(item: T) {
    var available = false
    private var sub: T = item

    fun fetch(): T? {
        return sub?.takeIf { available }
    }

    //多泛型参数
    fun <R> fetch(subFunction: (T) -> R): R? {
        return subFunction(sub).takeIf { available }
    }

    //想要通过[]操作符取值，可以重载运算符get函数
    operator fun get(index: Int): T? = sub?.takeIf { available }
}

class Dog(val weight: Int)


//泛型类型约束  只能传一个实例
class MagicBox2<T : Human>(item: T) {}
class Human(val weight: Int)

//vararg:可以传多个实例 ，传T的数组
class MagicBox3<T : Human>(vararg item: T) {}


// in(逆变)           泛型类只将泛型类型作为函数的入参    父类泛型对象可以赋值给子类泛型对象
// out(协变)          泛型类只将泛型类型作为函数的返回    子类泛型对象可以赋值给父类泛型对象
// invariant(不变)    泛型类既将泛型类型作为函数的入参，又将泛型类型作为函数的返回
interface Production<out T> {
    fun product(): T
}

interface Consumer<in T> {
    fun consume(item: T)
}

interface ProductionConsumer<T> {
    fun product(): T
    fun consume(item: T)
}

open class Food
open class FastFood : Food()
class Burger : FastFood()


//生产者
//食品商店
class FoodStore : Production<Food> {
    override fun product(): Food {
        println("product food.")
        return Food()
    }
}

//快餐商店
class FastFoodStore : Production<FastFood> {
    override fun product(): FastFood {
        println("product FastFood.")
        return FastFood()
    }
}

//汉堡商店
class BurgerStore : Production<Burger> {
    override fun product(): Burger {
        println("product Burger.")
        return Burger()
    }
}

//消费者
class EveryBody : Consumer<Food> {
    override fun consume(item: Food) {
        println("eat Food.")
    }
}

class ModernPeople : Consumer<FastFood> {
    override fun consume(item: FastFood) {
        println("eat FastFood.")
    }
}

class American : Consumer<Burger> {
    override fun consume(item: Burger) {
        println("eat Burger.")
    }
}


fun main() {
    val g: Gun = AK47(200)
    println(g.trigger())


    val box: MagicBox<Dog> = MagicBox(Dog(20))
    box.available = true
    println(box.fetch()?.run { println("you find $weight") })

    //想要通过[]操作符取值，可以重载运算符get函数
    box[0]

// out(协变)泛型类只将泛型类型作为函数的返回    子类泛型对象可以赋值给父类泛型对象
    val production1: Production<Food> = FoodStore()
    val production2: Production<Food> = FastFoodStore()
    val production3: Production<Food> = BurgerStore()

// in(逆变)泛型类只将泛型类型作为函数的入参    父类泛型对象可以赋值给子类泛型对象
    val consumer1: Consumer<Burger> = EveryBody()
    val consumer2: Consumer<Burger> = ModernPeople()
    val consumer3: Consumer<Burger> = American()
}

//4、reified 可以检查泛型参数类型  和内联函数inline一起使用
//（不管java还是kotlin不允许对泛型参数T做类型检查，泛型类型参数类型会被插除，T的类型信息在运行时时不可知的）





